package com.noassertions.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.index.CorruptIndexException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.noassertions.data.DAOInterface;
import com.noassertions.domain.Comment;
import com.noassertions.domain.Fit;
import com.noassertions.domain.Rider;
import com.noassertions.domain.User;
import com.noassertions.services.LuceneSearcher;

@Controller
public class SearchController
{
    protected final Log log = LogFactory.getLog(getClass());
    private final DAOInterface dao;
    private final LuceneSearcher searcher;

    @Autowired
    public SearchController(DAOInterface dao, LuceneSearcher searcher) {
        this.dao = dao;
        this.searcher = searcher;
    }    

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public String displaySearchForm(Model model) throws CorruptIndexException, IOException
    {

		// TODO this business of checking for a string (which indicates that user is not authenticated) is a total hack and should be factored out
		if (! (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String)) {
			UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			User user = dao.getUserByemailAddress(principal.getUsername());
			model.addAttribute("emailAddress", user.getEmailaddress());
		}

    	return "search";
    }	

	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public String displaySearchResults(Model model, HttpServletRequest request) throws CorruptIndexException, IOException
	{
		
    	String query = "";
    	boolean nameFlag = false;
    	boolean notesFlag = false;
    	boolean commentsFlag = false;
    	
    	Enumeration namesEnum = request.getParameterNames();
    	while (namesEnum.hasMoreElements()) {
			String paramName = (String)namesEnum.nextElement();
	
			if ("query".equals(paramName)) {query = request.getParameter(paramName);}
			if ("dropdown".equals(paramName)) {
				String dropDown[] = request.getParameterValues("dropdown");
				for (int i=0; i< dropDown.length; i++) {
					if("name".equals(dropDown[i])) {nameFlag = true;}
					if("notes".equals(dropDown[i])) {notesFlag =  true;}
					if("comments".equals(dropDown[i])) {commentsFlag =  true;}
				}
			}		

			// a bit of spam checking (this field is hidden in our form and should be empty)
			if (paramName.equals("bread")) {
				if (!"".equals(request.getParameter(paramName))) {
					log.debug("Possible spam, bread field was not empty");
					return "search";
				}
			}
		}
    	
    	ArrayList<Rider> riderList = new ArrayList<Rider>();
		ArrayList<Fit> fitList = new ArrayList<Fit>();

    	
    	// Process the params we pulled out above
    	if (!"".equals(query)) {
    		
    		if (nameFlag) {
    			//generate list of riders from listUserIds and place them in the view
    			ArrayList<Integer> listIds = searcher.search("firstname", query);
    			listIds.addAll(searcher.search("lastname", query));
    			for (Integer userId : listIds) {
    				//TODO: This dao method should only return one rider, fix
    				ArrayList<Rider> rider = dao.getRiderByUserId(userId);
    				ArrayList<User> user = dao.getUserByUserId(userId);
//    				//TODO: update dao. this business of accessing index 0 is lame
    				rider.get(0).setFirstname(user.get(0).getFirstname());
    				rider.get(0).setLastname(user.get(0).getLastname());
    				rider.get(0).setBirthdate(user.get(0).getBirthdate());
    				riderList.add(rider.get(0));
    			}
    		}
    		
    		if (notesFlag) {
    			//generate list of riders from listUserIds and place them in the view
    			ArrayList<Integer> listFitIds = searcher.search("fitnotes", query);
    			ArrayList<Integer> listUserIds = searcher.search("ridernotes", query);
    			
    			for (Integer fitId : listFitIds) {
    				Fit fit = dao.getFitByFitId(fitId);
    				User user = dao.getUserByFitId(fitId);
    				fit.setFirstname(user.getFirstname());
    				fit.setLastname(user.getLastname());
    				fitList.add(fit);
    			}
    			    			
    			for (Integer userId : listUserIds) {
    				//TODO: This dao method should only return one rider, fix
    				ArrayList<Rider> rider = dao.getRiderByUserId(userId);
    				ArrayList<User> user = dao.getUserByUserId(userId);
    				//TODO: update dao. this business of accessing index 0 is lame
    				rider.get(0).setFirstname(user.get(0).getFirstname());
    				rider.get(0).setLastname(user.get(0).getLastname());
    				rider.get(0).setBirthdate(user.get(0).getBirthdate());
    				riderList.add(rider.get(0));
    			}
    		}
    		
    		if (commentsFlag) {
    			//generate list of comments from listUserIds and place them in the view
    			ArrayList<Integer> listCommentIds = searcher.search("comment", query);
    	    	ArrayList<Comment> commentList = new ArrayList<Comment>();

    			
    			for (Integer commentId : listCommentIds) {
    				//TODO: This dao method should only return one rider, fix
    				Comment comment = dao.getCommentByCommentId(commentId);
    				commentList.add(comment);
    			}
    			model.addAttribute("comments", commentList);
    		}
    		
    		model.addAttribute("riders", riderList);
			model.addAttribute("fits", fitList);

    	}
    	else {
    		// TODO this business of checking for a string (which indicates that user is not authenticated) is a total hack and should be factored out
    		if (! (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String)) {
    			UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    			User user = dao.getUserByemailAddress(principal.getUsername());
    			model.addAttribute("emailAddress", user.getEmailaddress());
    		}
    		
    		return "search";
    	}
		
		// TODO this business of checking for a string (which indicates that user is not authenticated) is a total hack and should be factored out
		if (! (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String)) {
			UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			User user = dao.getUserByemailAddress(principal.getUsername());
			model.addAttribute("emailAddress", user.getEmailaddress());
		}
    	
    	return "searchresults";
	}	
	

}